﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Kinect;
using System.Diagnostics;
using System.Collections;
using Deb.Drivers;
using System.Windows.Threading;

namespace KinaestheticDebuggerEnvironment
{
    /// <summary>
    /// Interaction logic for Page1.xaml
    /// </summary>
    public partial class Page1 : Page
    {
        KinectSensor kinectSensor;
        private bool sensorConflict;

        private DispatcherTimer IDETimer;

        private VSDriver vs = new VSDriver();

        public Page1()
        {
            InitializeComponent();
            this.WindowHeight = 600;
            this.WindowWidth = 400;
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            if (kinectSensor != null)
            {
                if (kinectSensor.Status == KinectStatus.Connected)
                {
                    // View kinect viewer
                    if (this.gestureCheckBox.HasContent && this.speechCheckBox.HasContent)
                    {
                        Page2 page2 = new Page2(this.detectedIDEs.SelectedItem.ToString(), (bool)this.gestureCheckBox.IsChecked, (bool)this.speechCheckBox.IsChecked);
                        this.NavigationService.Navigate(page2);
                    }
                    else
                    {
                        MessageBox.Show("Gesture or speech recognition checkboxes are null!");
                    }
                }
                else
                {
                    MessageBox.Show("Kinect is disconnected");
                }
            }
            else
            {
                MessageBox.Show("Kinect is disconnected");
            }
        }

        private void Page_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                //listen to any status change for Kinects
                KinectSensor.KinectSensors.StatusChanged += Kinects_StatusChanged;
                DiscoverSensor();

                //Setup Timer that checks for new IDE instances
                IDETimer = new System.Windows.Threading.DispatcherTimer();
                IDETimer.Tick += new EventHandler(IDETimer_Tick);
                IDETimer.Interval = new TimeSpan(0, 0, 2);
                IDETimer.Start();

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            
        }

        private void IDETimer_Tick(object sender, EventArgs e)
        {
            LoadAvailableIDEs();
        }

        void Kinects_StatusChanged(object sender, StatusChangedEventArgs e)
        {
            var status = e.Status;
            if (this.kinectSensor == null)
            {
                this.UpdateStatus(status);
                if (e.Status == KinectStatus.Connected)
                {
                    this.kinectSensor = e.Sensor;
                    Initialize();
                }
            }
            else
            {
                if (this.kinectSensor == e.Sensor)
                {
                    this.UpdateStatus(status);
                    if (e.Status == KinectStatus.Disconnected ||
                        e.Status == KinectStatus.NotPowered)
                    {
                        this.kinectSensor = null;
                        this.sensorConflict = false;
                        this.DiscoverSensor();
                    }
                }
            }

            
        }

        private void UpdateStatus(KinectStatus status)
        {
            switch (status)
            {
                case KinectStatus.Connected:
                    // If there's a sensor conflict 
                    if (this.sensorConflict)
                    {
                        KinectStatusLabel.Content = "This Kinect is being used by another application";
                        KinectStatusTextBlock.Text = "Please close the other application using Kinect and restart this applications";
                    }
                    else
                    {
                        KinectStatusLabel.Content = "Kinect is connected";
                    }

                    break;
                case KinectStatus.DeviceNotGenuine:
                    KinectStatusLabel.Content = "This sensor is not genuine!";
                    KinectStatusTextBlock.Text = "This application needs a genuine Kinect for Windows sensor in order to function. Please plug one into the PC.";
                    break;
                case KinectStatus.DeviceNotSupported:
                    KinectStatusLabel.Content = "Device is not supported";
                    KinectStatusTextBlock.Text = "This application needs a Kinect for Windows sensor in order to function. Please plug one into the PC.";
                    break;
                case KinectStatus.Disconnected:
                    KinectStatusLabel.Content = "Kinect is disconnected";
                    KinectStatusTextBlock.Text = "This application needs a Kinect for Windows sensor in order to function. Please plug one into the PC.";
                    break;
                case KinectStatus.NotReady:
                case KinectStatus.Error:
                    KinectStatusLabel.Content = "Oops, there is an error";
                    KinectStatusTextBlock.Text = "The Kinect Sensor is plugged in, however an error has occured.";
                    break;
                case KinectStatus.Initializing:
                    KinectStatusLabel.Content = "Initializing...";
                    KinectStatusTextBlock.Text = "";
                    break;
                case KinectStatus.InsufficientBandwidth:
                    KinectStatusLabel.Content = "Too many USB devices! Please unplug one or more";
                    KinectStatusTextBlock.Text = "The Kinect Sensor needs the majority of the USB Bandwidth of a USB Controller. If other devices are in contention for that bandwidth, the Kinect Sensor may not be able to function.";
                    break;
                case KinectStatus.NotPowered:
                    KinectStatusLabel.Content = "Kinect is not powered";
                    KinectStatusTextBlock.Text = "The Kinect Sensor is plugged into the computer with its USB connection, but the power plug appears to be not powered.";
                    break;
                default:
                    KinectStatusLabel.Content = "Unhandled Status:";
                    KinectStatusTextBlock.Text = status.ToString();
                    break;
            }
        }

        private void DiscoverSensor()
        {
                // Find first sensor that is connected.
                foreach (KinectSensor sensor in KinectSensor.KinectSensors)
                {
                    if (sensor.Status == KinectStatus.Connected)
                    {
                        this.UpdateStatus(sensor.Status);
                        this.kinectSensor = sensor;
                        Initialize();
                        break;
                    }
                }

                // If we didn't find a connected Sensor
                if (this.kinectSensor == null)
                {
                    
                    // NOTE: this doesn't handle the multiple Kinect sensor case very well.
                    foreach (KinectSensor sensor in KinectSensor.KinectSensors)
                    {
                        this.UpdateStatus(sensor.Status);
                    }
                }
        }

        private void Initialize()
        {
            try
            {
                kinectSensor.Start();
            }
            catch (System.IO.IOException)
            {
                //this happens if another app is using the Kinect
                this.sensorConflict = true;

                // sensorConflict is considered when handling status updates,
                // so we call UpdateStatus with the current Status to ensure that the
                // logic takes the sensorConflict into account.
                this.UpdateStatus(this.kinectSensor.Status);
            }
        }

    }

}
